home *** CD-ROM | disk | FTP | other *** search
/ Introduction to 3D Game …ogramming with DirectX 12 / Introduction-to-3D-Game-Programming-with-DirectX-12.ISO / Code.Textures / Chapter 18 Cube Mapping / DynamicCube / DynamicCubeMapApp.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2016-03-02  |  52.7 KB  |  1,400 lines

  1. //***************************************************************************************
  2. // DynamicCubeMapApp.cpp by Frank Luna (C) 2015 All Rights Reserved.
  3. //***************************************************************************************
  4.  
  5. #include "../../Common/d3dApp.h"
  6. #include "../../Common/MathHelper.h"
  7. #include "../../Common/UploadBuffer.h"
  8. #include "../../Common/GeometryGenerator.h"
  9. #include "../../Common/Camera.h"
  10. #include "FrameResource.h"
  11. #include "CubeRenderTarget.h"
  12.  
  13. using Microsoft::WRL::ComPtr;
  14. using namespace DirectX;
  15. using namespace DirectX::PackedVector;
  16.  
  17. #pragma comment(lib, "d3dcompiler.lib")
  18. #pragma comment(lib, "D3D12.lib")
  19.  
  20. const int gNumFrameResources = 3;
  21.  
  22. const UINT CubeMapSize = 512;
  23.  
  24. // Lightweight structure stores parameters to draw a shape.  This will
  25. // vary from app-to-app.
  26. struct RenderItem
  27. {
  28.     RenderItem() = default;
  29.     RenderItem(const RenderItem& rhs) = delete;
  30.  
  31.     // World matrix of the shape that describes the object's local space
  32.     // relative to the world space, which defines the position, orientation,
  33.     // and scale of the object in the world.
  34.     XMFLOAT4X4 World = MathHelper::Identity4x4();
  35.  
  36.     XMFLOAT4X4 TexTransform = MathHelper::Identity4x4();
  37.  
  38.     // Dirty flag indicating the object data has changed and we need to update the constant buffer.
  39.     // Because we have an object cbuffer for each FrameResource, we have to apply the
  40.     // update to each FrameResource.  Thus, when we modify obect data we should set 
  41.     // NumFramesDirty = gNumFrameResources so that each frame resource gets the update.
  42.     int NumFramesDirty = gNumFrameResources;
  43.  
  44.     // Index into GPU constant buffer corresponding to the ObjectCB for this render item.
  45.     UINT ObjCBIndex = -1;
  46.  
  47.     Material* Mat = nullptr;
  48.     MeshGeometry* Geo = nullptr;
  49.  
  50.     // Primitive topology.
  51.     D3D12_PRIMITIVE_TOPOLOGY PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  52.  
  53.     // DrawIndexedInstanced parameters.
  54.     UINT IndexCount = 0;
  55.     UINT StartIndexLocation = 0;
  56.     int BaseVertexLocation = 0;
  57. };
  58.  
  59. enum class RenderLayer : int
  60. {
  61.     Opaque = 0,
  62.     OpaqueDynamicReflectors,
  63.     Sky,
  64.     Count
  65. };
  66.  
  67. class DynamicCubeMapApp : public D3DApp
  68. {
  69. public:
  70.     DynamicCubeMapApp(HINSTANCE hInstance);
  71.     DynamicCubeMapApp(const DynamicCubeMapApp& rhs) = delete;
  72.     DynamicCubeMapApp& operator=(const DynamicCubeMapApp& rhs) = delete;
  73.     ~DynamicCubeMapApp();
  74.  
  75.     virtual bool Initialize()override;
  76.  
  77. private:
  78.     virtual void CreateRtvAndDsvDescriptorHeaps()override;
  79.     virtual void OnResize()override;
  80.     virtual void Update(const GameTimer& gt)override;
  81.     virtual void Draw(const GameTimer& gt)override;
  82.  
  83.     virtual void OnMouseDown(WPARAM btnState, int x, int y)override;
  84.     virtual void OnMouseUp(WPARAM btnState, int x, int y)override;
  85.     virtual void OnMouseMove(WPARAM btnState, int x, int y)override;
  86.  
  87.     void OnKeyboardInput(const GameTimer& gt);
  88.     void AnimateMaterials(const GameTimer& gt);
  89.     void UpdateObjectCBs(const GameTimer& gt);
  90.     void UpdateMaterialBuffer(const GameTimer& gt);
  91.     void UpdateMainPassCB(const GameTimer& gt);
  92.     void UpdateCubeMapFacePassCBs();
  93.  
  94.     void LoadTextures();
  95.     void BuildRootSignature();
  96.     void BuildDescriptorHeaps();
  97.     void BuildCubeDepthStencil();
  98.     void BuildShadersAndInputLayout();
  99.     void BuildSkullGeometry();
  100.     void BuildShapeGeometry();
  101.     void BuildPSOs();
  102.     void BuildFrameResources();
  103.     void BuildMaterials();
  104.     void BuildRenderItems();
  105.     void DrawRenderItems(ID3D12GraphicsCommandList* cmdList, const std::vector<RenderItem*>& ritems);
  106.     void DrawSceneToCubeMap();
  107.  
  108.     std::array<const CD3DX12_STATIC_SAMPLER_DESC, 6> GetStaticSamplers();
  109.     void BuildCubeFaceCamera(float x, float y, float z);
  110.  
  111. private:
  112.  
  113.     std::vector<std::unique_ptr<FrameResource>> mFrameResources;
  114.     FrameResource* mCurrFrameResource = nullptr;
  115.     int mCurrFrameResourceIndex = 0;
  116.  
  117.     ComPtr<ID3D12RootSignature> mRootSignature = nullptr;
  118.  
  119.     ComPtr<ID3D12DescriptorHeap> mSrvDescriptorHeap = nullptr;
  120.  
  121.     ComPtr<ID3D12Resource> mCubeDepthStencilBuffer;
  122.  
  123.     std::unordered_map<std::string, std::unique_ptr<MeshGeometry>> mGeometries;
  124.     std::unordered_map<std::string, std::unique_ptr<Material>> mMaterials;
  125.     std::unordered_map<std::string, std::unique_ptr<Texture>> mTextures;
  126.     std::unordered_map<std::string, ComPtr<ID3DBlob>> mShaders;
  127.     std::unordered_map<std::string, ComPtr<ID3D12PipelineState>> mPSOs;
  128.  
  129.     std::vector<D3D12_INPUT_ELEMENT_DESC> mInputLayout;
  130.  
  131.     // List of all the render items.
  132.     std::vector<std::unique_ptr<RenderItem>> mAllRitems;
  133.  
  134.     // Render items divided by PSO.
  135.     std::vector<RenderItem*> mRitemLayer[(int)RenderLayer::Count];
  136.  
  137.     UINT mSkyTexHeapIndex = 0;
  138.     UINT mDynamicTexHeapIndex = 0;
  139.  
  140.     RenderItem* mSkullRitem = nullptr;
  141.  
  142.     std::unique_ptr<CubeRenderTarget> mDynamicCubeMap = nullptr;
  143.     CD3DX12_CPU_DESCRIPTOR_HANDLE mCubeDSV;
  144.  
  145.     PassConstants mMainPassCB;
  146.  
  147.     Camera mCamera;
  148.     Camera mCubeMapCamera[6];
  149.  
  150.     POINT mLastMousePos;
  151. };
  152.  
  153. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
  154.     PSTR cmdLine, int showCmd)
  155. {
  156.     // Enable run-time memory check for debug builds.
  157. #if defined(DEBUG) | defined(_DEBUG)
  158.     _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
  159. #endif
  160.  
  161.     try
  162.     {
  163.         DynamicCubeMapApp theApp(hInstance);
  164.         if(!theApp.Initialize())
  165.             return 0;
  166.  
  167.         return theApp.Run();
  168.     }
  169.     catch(DxException& e)
  170.     {
  171.         MessageBox(nullptr, e.ToString().c_str(), L"HR Failed", MB_OK);
  172.         return 0;
  173.     }
  174. }
  175.  
  176. DynamicCubeMapApp::DynamicCubeMapApp(HINSTANCE hInstance)
  177.     : D3DApp(hInstance)
  178. {
  179. }
  180.  
  181. DynamicCubeMapApp::~DynamicCubeMapApp()
  182. {
  183.     if(md3dDevice != nullptr)
  184.         FlushCommandQueue();
  185. }
  186.  
  187. bool DynamicCubeMapApp::Initialize()
  188. {
  189.     if(!D3DApp::Initialize())
  190.         return false;
  191.  
  192.     // Reset the command list to prep for initialization commands.
  193.     ThrowIfFailed(mCommandList->Reset(mDirectCmdListAlloc.Get(), nullptr));
  194.  
  195.     mCamera.SetPosition(0.0f, 2.0f, -15.0f);
  196.  
  197.     BuildCubeFaceCamera(0.0f, 2.0f, 0.0f);
  198.  
  199.     mDynamicCubeMap = std::make_unique<CubeRenderTarget>(md3dDevice.Get(), 
  200.         CubeMapSize, CubeMapSize, DXGI_FORMAT_R8G8B8A8_UNORM);
  201.  
  202.     LoadTextures();
  203.     BuildRootSignature();
  204.     BuildDescriptorHeaps();
  205.     BuildCubeDepthStencil();
  206.     BuildShadersAndInputLayout();
  207.     BuildSkullGeometry();
  208.     BuildShapeGeometry();
  209.     BuildMaterials();
  210.     BuildRenderItems();
  211.     BuildFrameResources();
  212.     BuildPSOs();
  213.  
  214.     // Execute the initialization commands.
  215.     ThrowIfFailed(mCommandList->Close());
  216.     ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
  217.     mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
  218.  
  219.     // Wait until initialization is complete.
  220.     FlushCommandQueue();
  221.  
  222.     return true;
  223. }
  224.  
  225. void DynamicCubeMapApp::CreateRtvAndDsvDescriptorHeaps()
  226. {
  227.     // Add +6 RTV for cube render target.
  228.     D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc;
  229.     rtvHeapDesc.NumDescriptors = SwapChainBufferCount + 6;
  230.     rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
  231.     rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
  232.     rtvHeapDesc.NodeMask = 0;
  233.     ThrowIfFailed(md3dDevice->CreateDescriptorHeap(
  234.         &rtvHeapDesc, IID_PPV_ARGS(mRtvHeap.GetAddressOf())));
  235.  
  236.     // Add +1 DSV for cube render target.
  237.     D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc;
  238.     dsvHeapDesc.NumDescriptors = 2;
  239.     dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
  240.     dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
  241.     dsvHeapDesc.NodeMask = 0;
  242.     ThrowIfFailed(md3dDevice->CreateDescriptorHeap(
  243.         &dsvHeapDesc, IID_PPV_ARGS(mDsvHeap.GetAddressOf())));
  244.  
  245.     mCubeDSV = CD3DX12_CPU_DESCRIPTOR_HANDLE(
  246.         mDsvHeap->GetCPUDescriptorHandleForHeapStart(),
  247.         1,
  248.         mDsvDescriptorSize);
  249. }
  250.  
  251. void DynamicCubeMapApp::OnResize()
  252. {
  253.     D3DApp::OnResize();
  254.  
  255.     mCamera.SetLens(0.25f*MathHelper::Pi, AspectRatio(), 1.0f, 1000.0f);
  256. }
  257.  
  258. void DynamicCubeMapApp::Update(const GameTimer& gt)
  259. {
  260.     OnKeyboardInput(gt);
  261.  
  262.     //
  263.     // Animate the skull around the center sphere.
  264.     //
  265.  
  266.     XMMATRIX skullScale = XMMatrixScaling(0.2f, 0.2f, 0.2f);
  267.     XMMATRIX skullOffset = XMMatrixTranslation(3.0f, 2.0f, 0.0f);
  268.     XMMATRIX skullLocalRotate = XMMatrixRotationY(2.0f*gt.TotalTime());
  269.     XMMATRIX skullGlobalRotate = XMMatrixRotationY(0.5f*gt.TotalTime());
  270.     XMStoreFloat4x4(&mSkullRitem->World, skullScale*skullLocalRotate*skullOffset*skullGlobalRotate);
  271.     mSkullRitem->NumFramesDirty = gNumFrameResources;
  272.  
  273.     // Cycle through the circular frame resource array.
  274.     mCurrFrameResourceIndex = (mCurrFrameResourceIndex + 1) % gNumFrameResources;
  275.     mCurrFrameResource = mFrameResources[mCurrFrameResourceIndex].get();
  276.  
  277.     // Has the GPU finished processing the commands of the current frame resource?
  278.     // If not, wait until the GPU has completed commands up to this fence point.
  279.     if(mCurrFrameResource->Fence != 0 && mFence->GetCompletedValue() < mCurrFrameResource->Fence)
  280.     {
  281.         HANDLE eventHandle = CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS);
  282.         ThrowIfFailed(mFence->SetEventOnCompletion(mCurrFrameResource->Fence, eventHandle));
  283.         WaitForSingleObject(eventHandle, INFINITE);
  284.         CloseHandle(eventHandle);
  285.     }
  286.  
  287.     AnimateMaterials(gt);
  288.     UpdateObjectCBs(gt);
  289.     UpdateMaterialBuffer(gt);
  290.     UpdateMainPassCB(gt);
  291. }
  292.  
  293. void DynamicCubeMapApp::Draw(const GameTimer& gt)
  294. {
  295.     auto cmdListAlloc = mCurrFrameResource->CmdListAlloc;
  296.  
  297.     // Reuse the memory associated with command recording.
  298.     // We can only reset when the associated command lists have finished execution on the GPU.
  299.     ThrowIfFailed(cmdListAlloc->Reset());
  300.  
  301.     // A command list can be reset after it has been added to the command queue via ExecuteCommandList.
  302.     // Reusing the command list reuses memory.
  303.     ThrowIfFailed(mCommandList->Reset(cmdListAlloc.Get(), mPSOs["opaque"].Get()));
  304.  
  305.     ID3D12DescriptorHeap* descriptorHeaps[] = { mSrvDescriptorHeap.Get() };
  306.     mCommandList->SetDescriptorHeaps(_countof(descriptorHeaps), descriptorHeaps);
  307.  
  308.     mCommandList->SetGraphicsRootSignature(mRootSignature.Get());
  309.  
  310.     // Bind all the materials used in this scene.  For structured buffers, we can bypass the heap and 
  311.     // set as a root descriptor.
  312.     auto matBuffer = mCurrFrameResource->MaterialBuffer->Resource();
  313.     mCommandList->SetGraphicsRootShaderResourceView(2, matBuffer->GetGPUVirtualAddress());
  314.  
  315.     // Bind the sky cube map.  For our demos, we just use one "world" cube map representing the environment
  316.     // from far away, so all objects will use the same cube map and we only need to set it once per-frame.  
  317.     // If we wanted to use "local" cube maps, we would have to change them per-object, or dynamically
  318.     // index into an array of cube maps.
  319.  
  320.     CD3DX12_GPU_DESCRIPTOR_HANDLE skyTexDescriptor(mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
  321.     skyTexDescriptor.Offset(mSkyTexHeapIndex, mCbvSrvUavDescriptorSize);
  322.     mCommandList->SetGraphicsRootDescriptorTable(3, skyTexDescriptor);
  323.  
  324.     // Bind all the textures used in this scene.  Observe
  325.     // that we only have to specify the first descriptor in the table.  
  326.     // The root signature knows how many descriptors are expected in the table.
  327.     mCommandList->SetGraphicsRootDescriptorTable(4, mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
  328.  
  329.     DrawSceneToCubeMap();
  330.  
  331.     mCommandList->RSSetViewports(1, &mScreenViewport);
  332.     mCommandList->RSSetScissorRects(1, &mScissorRect);
  333.  
  334.     // Indicate a state transition on the resource usage.
  335.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
  336.         D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));
  337.  
  338.     // Clear the back buffer and depth buffer.
  339.     mCommandList->ClearRenderTargetView(CurrentBackBufferView(), Colors::LightSteelBlue, 0, nullptr);
  340.     mCommandList->ClearDepthStencilView(DepthStencilView(), D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr);
  341.  
  342.     // Specify the buffers we are going to render to.
  343.     mCommandList->OMSetRenderTargets(1, &CurrentBackBufferView(), true, &DepthStencilView());
  344.  
  345.     auto passCB = mCurrFrameResource->PassCB->Resource();
  346.     mCommandList->SetGraphicsRootConstantBufferView(1, passCB->GetGPUVirtualAddress());
  347.  
  348.  
  349.     // Use the dynamic cube map for the dynamic reflectors layer.
  350.     CD3DX12_GPU_DESCRIPTOR_HANDLE dynamicTexDescriptor(mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
  351.     dynamicTexDescriptor.Offset(mSkyTexHeapIndex + 1, mCbvSrvUavDescriptorSize);
  352.     mCommandList->SetGraphicsRootDescriptorTable(3, dynamicTexDescriptor);
  353.  
  354.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::OpaqueDynamicReflectors]);
  355.  
  356.     // Use the static "background" cube map for the other objects (including the sky)
  357.     mCommandList->SetGraphicsRootDescriptorTable(3, skyTexDescriptor);
  358.  
  359.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Opaque]);
  360.  
  361.     mCommandList->SetPipelineState(mPSOs["sky"].Get());
  362.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Sky]);
  363.  
  364.     // Indicate a state transition on the resource usage.
  365.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
  366.         D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));
  367.  
  368.     // Done recording commands.
  369.     ThrowIfFailed(mCommandList->Close());
  370.  
  371.     // Add the command list to the queue for execution.
  372.     ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
  373.     mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
  374.  
  375.     // Swap the back and front buffers
  376.     ThrowIfFailed(mSwapChain->Present(0, 0));
  377.     mCurrBackBuffer = (mCurrBackBuffer + 1) % SwapChainBufferCount;
  378.  
  379.     // Advance the fence value to mark commands up to this fence point.
  380.     mCurrFrameResource->Fence = ++mCurrentFence;
  381.  
  382.     // Add an instruction to the command queue to set a new fence point. 
  383.     // Because we are on the GPU timeline, the new fence point won't be 
  384.     // set until the GPU finishes processing all the commands prior to this Signal().
  385.     mCommandQueue->Signal(mFence.Get(), mCurrentFence);
  386. }
  387.  
  388. void DynamicCubeMapApp::OnMouseDown(WPARAM btnState, int x, int y)
  389. {
  390.     mLastMousePos.x = x;
  391.     mLastMousePos.y = y;
  392.  
  393.     SetCapture(mhMainWnd);
  394. }
  395.  
  396. void DynamicCubeMapApp::OnMouseUp(WPARAM btnState, int x, int y)
  397. {
  398.     ReleaseCapture();
  399. }
  400.  
  401. void DynamicCubeMapApp::OnMouseMove(WPARAM btnState, int x, int y)
  402. {
  403.     if((btnState & MK_LBUTTON) != 0)
  404.     {
  405.         // Make each pixel correspond to a quarter of a degree.
  406.         float dx = XMConvertToRadians(0.25f*static_cast<float>(x - mLastMousePos.x));
  407.         float dy = XMConvertToRadians(0.25f*static_cast<float>(y - mLastMousePos.y));
  408.  
  409.         mCamera.Pitch(dy);
  410.         mCamera.RotateY(dx);
  411.     }
  412.  
  413.     mLastMousePos.x = x;
  414.     mLastMousePos.y = y;
  415. }
  416.  
  417. void DynamicCubeMapApp::OnKeyboardInput(const GameTimer& gt)
  418. {
  419.     const float dt = gt.DeltaTime();
  420.  
  421.     if(GetAsyncKeyState('W') & 0x8000)
  422.         mCamera.Walk(10.0f*dt);
  423.  
  424.     if(GetAsyncKeyState('S') & 0x8000)
  425.         mCamera.Walk(-10.0f*dt);
  426.  
  427.     if(GetAsyncKeyState('A') & 0x8000)
  428.         mCamera.Strafe(-10.0f*dt);
  429.  
  430.     if(GetAsyncKeyState('D') & 0x8000)
  431.         mCamera.Strafe(10.0f*dt);
  432.  
  433.     mCamera.UpdateViewMatrix();
  434. }
  435.  
  436. void DynamicCubeMapApp::AnimateMaterials(const GameTimer& gt)
  437. {
  438.     
  439. }
  440.  
  441. void DynamicCubeMapApp::UpdateObjectCBs(const GameTimer& gt)
  442. {
  443.     auto currObjectCB = mCurrFrameResource->ObjectCB.get();
  444.     for(auto& e : mAllRitems)
  445.     {
  446.         // Only update the cbuffer data if the constants have changed.  
  447.         // This needs to be tracked per frame resource.
  448.         if(e->NumFramesDirty > 0)
  449.         {
  450.             XMMATRIX world = XMLoadFloat4x4(&e->World);
  451.             XMMATRIX texTransform = XMLoadFloat4x4(&e->TexTransform);
  452.  
  453.             ObjectConstants objConstants;
  454.             XMStoreFloat4x4(&objConstants.World, XMMatrixTranspose(world));
  455.             XMStoreFloat4x4(&objConstants.TexTransform, XMMatrixTranspose(texTransform));
  456.             objConstants.MaterialIndex = e->Mat->MatCBIndex;
  457.  
  458.             currObjectCB->CopyData(e->ObjCBIndex, objConstants);
  459.  
  460.             // Next FrameResource need to be updated too.
  461.             e->NumFramesDirty--;
  462.         }
  463.     }
  464. }
  465.  
  466. void DynamicCubeMapApp::UpdateMaterialBuffer(const GameTimer& gt)
  467. {
  468.     auto currMaterialBuffer = mCurrFrameResource->MaterialBuffer.get();
  469.     for(auto& e : mMaterials)
  470.     {
  471.         // Only update the cbuffer data if the constants have changed.  If the cbuffer
  472.         // data changes, it needs to be updated for each FrameResource.
  473.         Material* mat = e.second.get();
  474.         if(mat->NumFramesDirty > 0)
  475.         {
  476.             XMMATRIX matTransform = XMLoadFloat4x4(&mat->MatTransform);
  477.  
  478.             MaterialData matData;
  479.             matData.DiffuseAlbedo = mat->DiffuseAlbedo;
  480.             matData.FresnelR0 = mat->FresnelR0;
  481.             matData.Roughness = mat->Roughness;
  482.             XMStoreFloat4x4(&matData.MatTransform, XMMatrixTranspose(matTransform));
  483.             matData.DiffuseMapIndex = mat->DiffuseSrvHeapIndex;
  484.  
  485.             currMaterialBuffer->CopyData(mat->MatCBIndex, matData);
  486.  
  487.             // Next FrameResource need to be updated too.
  488.             mat->NumFramesDirty--;
  489.         }
  490.     }
  491. }
  492.  
  493. void DynamicCubeMapApp::UpdateMainPassCB(const GameTimer& gt)
  494. {
  495.     XMMATRIX view = mCamera.GetView();
  496.     XMMATRIX proj = mCamera.GetProj();
  497.  
  498.     XMMATRIX viewProj = XMMatrixMultiply(view, proj);
  499.     XMMATRIX invView = XMMatrixInverse(&XMMatrixDeterminant(view), view);
  500.     XMMATRIX invProj = XMMatrixInverse(&XMMatrixDeterminant(proj), proj);
  501.     XMMATRIX invViewProj = XMMatrixInverse(&XMMatrixDeterminant(viewProj), viewProj);
  502.  
  503.     XMStoreFloat4x4(&mMainPassCB.View, XMMatrixTranspose(view));
  504.     XMStoreFloat4x4(&mMainPassCB.InvView, XMMatrixTranspose(invView));
  505.     XMStoreFloat4x4(&mMainPassCB.Proj, XMMatrixTranspose(proj));
  506.     XMStoreFloat4x4(&mMainPassCB.InvProj, XMMatrixTranspose(invProj));
  507.     XMStoreFloat4x4(&mMainPassCB.ViewProj, XMMatrixTranspose(viewProj));
  508.     XMStoreFloat4x4(&mMainPassCB.InvViewProj, XMMatrixTranspose(invViewProj));
  509.     mMainPassCB.EyePosW = mCamera.GetPosition3f();
  510.     mMainPassCB.RenderTargetSize = XMFLOAT2((float)mClientWidth, (float)mClientHeight);
  511.     mMainPassCB.InvRenderTargetSize = XMFLOAT2(1.0f / mClientWidth, 1.0f / mClientHeight);
  512.     mMainPassCB.NearZ = 1.0f;
  513.     mMainPassCB.FarZ = 1000.0f;
  514.     mMainPassCB.TotalTime = gt.TotalTime();
  515.     mMainPassCB.DeltaTime = gt.DeltaTime();
  516.     mMainPassCB.AmbientLight = { 0.25f, 0.25f, 0.35f, 1.0f };
  517.     mMainPassCB.Lights[0].Direction = { 0.57735f, -0.57735f, 0.57735f };
  518.     mMainPassCB.Lights[0].Strength = { 0.8f, 0.8f, 0.8f };
  519.     mMainPassCB.Lights[1].Direction = { -0.57735f, -0.57735f, 0.57735f };
  520.     mMainPassCB.Lights[1].Strength = { 0.4f, 0.4f, 0.4f };
  521.     mMainPassCB.Lights[2].Direction = { 0.0f, -0.707f, -0.707f };
  522.     mMainPassCB.Lights[2].Strength = { 0.2f, 0.2f, 0.2f };
  523.  
  524.     auto currPassCB = mCurrFrameResource->PassCB.get();
  525.     currPassCB->CopyData(0, mMainPassCB);
  526.  
  527.     UpdateCubeMapFacePassCBs();
  528. }
  529.  
  530. void DynamicCubeMapApp::UpdateCubeMapFacePassCBs()
  531. {
  532.     for(int i = 0; i < 6; ++i)
  533.     {
  534.         PassConstants cubeFacePassCB = mMainPassCB;
  535.  
  536.         XMMATRIX view = mCubeMapCamera[i].GetView();
  537.         XMMATRIX proj = mCubeMapCamera[i].GetProj();
  538.  
  539.         XMMATRIX viewProj = XMMatrixMultiply(view, proj);
  540.         XMMATRIX invView = XMMatrixInverse(&XMMatrixDeterminant(view), view);
  541.         XMMATRIX invProj = XMMatrixInverse(&XMMatrixDeterminant(proj), proj);
  542.         XMMATRIX invViewProj = XMMatrixInverse(&XMMatrixDeterminant(viewProj), viewProj);
  543.  
  544.         XMStoreFloat4x4(&cubeFacePassCB.View, XMMatrixTranspose(view));
  545.         XMStoreFloat4x4(&cubeFacePassCB.InvView, XMMatrixTranspose(invView));
  546.         XMStoreFloat4x4(&cubeFacePassCB.Proj, XMMatrixTranspose(proj));
  547.         XMStoreFloat4x4(&cubeFacePassCB.InvProj, XMMatrixTranspose(invProj));
  548.         XMStoreFloat4x4(&cubeFacePassCB.ViewProj, XMMatrixTranspose(viewProj));
  549.         XMStoreFloat4x4(&cubeFacePassCB.InvViewProj, XMMatrixTranspose(invViewProj));
  550.         cubeFacePassCB.EyePosW = mCubeMapCamera[i].GetPosition3f();
  551.         cubeFacePassCB.RenderTargetSize = XMFLOAT2((float)CubeMapSize, (float)CubeMapSize);
  552.         cubeFacePassCB.InvRenderTargetSize = XMFLOAT2(1.0f / CubeMapSize, 1.0f / CubeMapSize);
  553.  
  554.         auto currPassCB = mCurrFrameResource->PassCB.get();
  555.  
  556.         // Cube map pass cbuffers are stored in elements 1-6.
  557.         currPassCB->CopyData(1 + i, cubeFacePassCB);
  558.     }
  559. }
  560.  
  561. void DynamicCubeMapApp::LoadTextures()
  562. {
  563.     std::vector<std::string> texNames =
  564.     {
  565.         "bricksDiffuseMap",
  566.         "tileDiffuseMap",
  567.         "defaultDiffuseMap",
  568.         "skyCubeMap"
  569.     };
  570.  
  571.     std::vector<std::wstring> texFilenames =
  572.     {
  573.         L"../../Textures/bricks2.dds",
  574.         L"../../Textures/tile.dds",
  575.         L"../../Textures/white1x1.dds",
  576.         L"../../Textures/grasscube1024.dds"
  577.     };
  578.  
  579.     for (int i = 0; i < (int)texNames.size(); ++i)
  580.     {
  581.         auto texMap = std::make_unique<Texture>();
  582.         texMap->Name = texNames[i];
  583.         texMap->Filename = texFilenames[i];
  584.         ThrowIfFailed(DirectX::CreateDDSTextureFromFile12(md3dDevice.Get(),
  585.             mCommandList.Get(), texMap->Filename.c_str(),
  586.             texMap->Resource, texMap->UploadHeap));
  587.  
  588.         mTextures[texMap->Name] = std::move(texMap);
  589.     }
  590. }
  591.  
  592. void DynamicCubeMapApp::BuildRootSignature()
  593. {
  594.     CD3DX12_DESCRIPTOR_RANGE texTable0;
  595.     texTable0.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0, 0);
  596.  
  597.     CD3DX12_DESCRIPTOR_RANGE texTable1;
  598.     texTable1.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 5, 1, 0);
  599.  
  600.     // Root parameter can be a table, root descriptor or root constants.
  601.     CD3DX12_ROOT_PARAMETER slotRootParameter[5];
  602.  
  603.     // Perfomance TIP: Order from most frequent to least frequent.
  604.     slotRootParameter[0].InitAsConstantBufferView(0);
  605.     slotRootParameter[1].InitAsConstantBufferView(1);
  606.     slotRootParameter[2].InitAsShaderResourceView(0, 1);
  607.     slotRootParameter[3].InitAsDescriptorTable(1, &texTable0, D3D12_SHADER_VISIBILITY_PIXEL);
  608.     slotRootParameter[4].InitAsDescriptorTable(1, &texTable1, D3D12_SHADER_VISIBILITY_PIXEL);
  609.  
  610.  
  611.     auto staticSamplers = GetStaticSamplers();
  612.  
  613.     // A root signature is an array of root parameters.
  614.     CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(5, slotRootParameter,
  615.         (UINT)staticSamplers.size(), staticSamplers.data(),
  616.         D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
  617.  
  618.     // create a root signature with a single slot which points to a descriptor range consisting of a single constant buffer
  619.     ComPtr<ID3DBlob> serializedRootSig = nullptr;
  620.     ComPtr<ID3DBlob> errorBlob = nullptr;
  621.     HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1,
  622.         serializedRootSig.GetAddressOf(), errorBlob.GetAddressOf());
  623.  
  624.     if(errorBlob != nullptr)
  625.     {
  626.         ::OutputDebugStringA((char*)errorBlob->GetBufferPointer());
  627.     }
  628.     ThrowIfFailed(hr);
  629.  
  630.     ThrowIfFailed(md3dDevice->CreateRootSignature(
  631.         0,
  632.         serializedRootSig->GetBufferPointer(),
  633.         serializedRootSig->GetBufferSize(),
  634.         IID_PPV_ARGS(mRootSignature.GetAddressOf())));
  635. }
  636.  
  637. void DynamicCubeMapApp::BuildDescriptorHeaps()
  638. {
  639.     //
  640.     // Create the SRV heap.
  641.     //
  642.     D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {};
  643.     srvHeapDesc.NumDescriptors = 6;
  644.     srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
  645.     srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
  646.     ThrowIfFailed(md3dDevice->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&mSrvDescriptorHeap)));
  647.  
  648.     //
  649.     // Fill out the heap with actual descriptors.
  650.     //
  651.     CD3DX12_CPU_DESCRIPTOR_HANDLE hDescriptor(mSrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
  652.  
  653.     auto bricksTex = mTextures["bricksDiffuseMap"]->Resource;
  654.     auto tileTex = mTextures["tileDiffuseMap"]->Resource;
  655.     auto whiteTex = mTextures["defaultDiffuseMap"]->Resource;
  656.     auto skyTex = mTextures["skyCubeMap"]->Resource;
  657.  
  658.     D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
  659.     srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
  660.     srvDesc.Format = bricksTex->GetDesc().Format;
  661.     srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
  662.     srvDesc.Texture2D.MostDetailedMip = 0;
  663.     srvDesc.Texture2D.MipLevels = bricksTex->GetDesc().MipLevels;
  664.     srvDesc.Texture2D.ResourceMinLODClamp = 0.0f;
  665.     md3dDevice->CreateShaderResourceView(bricksTex.Get(), &srvDesc, hDescriptor);
  666.  
  667.     // next descriptor
  668.     hDescriptor.Offset(1, mCbvSrvUavDescriptorSize);
  669.  
  670.     srvDesc.Format = tileTex->GetDesc().Format;
  671.     srvDesc.Texture2D.MipLevels = tileTex->GetDesc().MipLevels;
  672.     md3dDevice->CreateShaderResourceView(tileTex.Get(), &srvDesc, hDescriptor);
  673.  
  674.     // next descriptor
  675.     hDescriptor.Offset(1, mCbvSrvUavDescriptorSize);
  676.  
  677.     srvDesc.Format = whiteTex->GetDesc().Format;
  678.     srvDesc.Texture2D.MipLevels = whiteTex->GetDesc().MipLevels;
  679.     md3dDevice->CreateShaderResourceView(whiteTex.Get(), &srvDesc, hDescriptor);
  680.  
  681.     // next descriptor
  682.     hDescriptor.Offset(1, mCbvSrvUavDescriptorSize);
  683.  
  684.     srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
  685.     srvDesc.TextureCube.MostDetailedMip = 0;
  686.     srvDesc.TextureCube.MipLevels = skyTex->GetDesc().MipLevels;
  687.     srvDesc.TextureCube.ResourceMinLODClamp = 0.0f;
  688.     srvDesc.Format = skyTex->GetDesc().Format;
  689.     md3dDevice->CreateShaderResourceView(skyTex.Get(), &srvDesc, hDescriptor);
  690.     
  691.     mSkyTexHeapIndex = 3;
  692.     mDynamicTexHeapIndex = mSkyTexHeapIndex+1;
  693.  
  694.     auto srvCpuStart = mSrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart();
  695.     auto srvGpuStart = mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart();
  696.     auto rtvCpuStart = mRtvHeap->GetCPUDescriptorHandleForHeapStart();
  697.  
  698.     // Cubemap RTV goes after the swap chain descriptors.
  699.     int rtvOffset = SwapChainBufferCount;
  700.  
  701.     CD3DX12_CPU_DESCRIPTOR_HANDLE cubeRtvHandles[6];
  702.     for(int i = 0; i < 6; ++i)
  703.         cubeRtvHandles[i] = CD3DX12_CPU_DESCRIPTOR_HANDLE(rtvCpuStart, rtvOffset + i, mRtvDescriptorSize);
  704.  
  705.     // Dynamic cubemap SRV is after the sky SRV.
  706.     mDynamicCubeMap->BuildDescriptors(
  707.         CD3DX12_CPU_DESCRIPTOR_HANDLE(srvCpuStart, mDynamicTexHeapIndex, mCbvSrvUavDescriptorSize),
  708.         CD3DX12_GPU_DESCRIPTOR_HANDLE(srvGpuStart, mDynamicTexHeapIndex, mCbvSrvUavDescriptorSize),
  709.         cubeRtvHandles);
  710. }
  711.  
  712. void DynamicCubeMapApp::BuildCubeDepthStencil()
  713. {
  714.     // Create the depth/stencil buffer and view.
  715.     D3D12_RESOURCE_DESC depthStencilDesc;
  716.     depthStencilDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
  717.     depthStencilDesc.Alignment = 0;
  718.     depthStencilDesc.Width = CubeMapSize;
  719.     depthStencilDesc.Height = CubeMapSize;
  720.     depthStencilDesc.DepthOrArraySize = 1;
  721.     depthStencilDesc.MipLevels = 1;
  722.     depthStencilDesc.Format = mDepthStencilFormat;
  723.     depthStencilDesc.SampleDesc.Count = 1;
  724.     depthStencilDesc.SampleDesc.Quality = 0;
  725.     depthStencilDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
  726.     depthStencilDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
  727.  
  728.     D3D12_CLEAR_VALUE optClear;
  729.     optClear.Format = mDepthStencilFormat;
  730.     optClear.DepthStencil.Depth = 1.0f;
  731.     optClear.DepthStencil.Stencil = 0;
  732.     ThrowIfFailed(md3dDevice->CreateCommittedResource(
  733.         &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
  734.         D3D12_HEAP_FLAG_NONE,
  735.         &depthStencilDesc,
  736.         D3D12_RESOURCE_STATE_COMMON,
  737.         &optClear,
  738.         IID_PPV_ARGS(mCubeDepthStencilBuffer.GetAddressOf())));
  739.  
  740.     // Create descriptor to mip level 0 of entire resource using the format of the resource.
  741.     md3dDevice->CreateDepthStencilView(mCubeDepthStencilBuffer.Get(), nullptr, mCubeDSV);
  742.  
  743.     // Transition the resource from its initial state to be used as a depth buffer.
  744.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mCubeDepthStencilBuffer.Get(),
  745.         D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_DEPTH_WRITE));
  746. }
  747.  
  748. void DynamicCubeMapApp::BuildShadersAndInputLayout()
  749. {
  750.     const D3D_SHADER_MACRO alphaTestDefines[] =
  751.     {
  752.         "ALPHA_TEST", "1",
  753.         NULL, NULL
  754.     };
  755.  
  756.     mShaders["standardVS"] = d3dUtil::CompileShader(L"Shaders\\Default.hlsl", nullptr, "VS", "vs_5_1");
  757.     mShaders["opaquePS"] = d3dUtil::CompileShader(L"Shaders\\Default.hlsl", nullptr, "PS", "ps_5_1");
  758.     
  759.     mShaders["skyVS"] = d3dUtil::CompileShader(L"Shaders\\Sky.hlsl", nullptr, "VS", "vs_5_1");
  760.     mShaders["skyPS"] = d3dUtil::CompileShader(L"Shaders\\Sky.hlsl", nullptr, "PS", "ps_5_1");
  761.  
  762.     mInputLayout =
  763.     {
  764.         { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  765.         { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  766.         { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  767.     };
  768. }
  769.  
  770. void DynamicCubeMapApp::BuildSkullGeometry()
  771. {
  772.     std::ifstream fin("Models/skull.txt");
  773.  
  774.     if(!fin)
  775.     {
  776.         MessageBox(0, L"Models/skull.txt not found.", 0, 0);
  777.         return;
  778.     }
  779.  
  780.     UINT vcount = 0;
  781.     UINT tcount = 0;
  782.     std::string ignore;
  783.  
  784.     fin >> ignore >> vcount;
  785.     fin >> ignore >> tcount;
  786.     fin >> ignore >> ignore >> ignore >> ignore;
  787.  
  788.     XMFLOAT3 vMinf3(+MathHelper::Infinity, +MathHelper::Infinity, +MathHelper::Infinity);
  789.     XMFLOAT3 vMaxf3(-MathHelper::Infinity, -MathHelper::Infinity, -MathHelper::Infinity);
  790.  
  791.     XMVECTOR vMin = XMLoadFloat3(&vMinf3);
  792.     XMVECTOR vMax = XMLoadFloat3(&vMaxf3);
  793.  
  794.     std::vector<Vertex> vertices(vcount);
  795.     for(UINT i = 0; i < vcount; ++i)
  796.     {
  797.         fin >> vertices[i].Pos.x >> vertices[i].Pos.y >> vertices[i].Pos.z;
  798.         fin >> vertices[i].Normal.x >> vertices[i].Normal.y >> vertices[i].Normal.z;
  799.  
  800.         vertices[i].TexC = { 0.0f, 0.0f };
  801.  
  802.         XMVECTOR P = XMLoadFloat3(&vertices[i].Pos);
  803.  
  804.         vMin = XMVectorMin(vMin, P);
  805.         vMax = XMVectorMax(vMax, P);
  806.     }
  807.  
  808.     BoundingBox bounds;
  809.     XMStoreFloat3(&bounds.Center, 0.5f*(vMin + vMax));
  810.     XMStoreFloat3(&bounds.Extents, 0.5f*(vMax - vMin));
  811.  
  812.     fin >> ignore;
  813.     fin >> ignore;
  814.     fin >> ignore;
  815.  
  816.     std::vector<std::int32_t> indices(3 * tcount);
  817.     for(UINT i = 0; i < tcount; ++i)
  818.     {
  819.         fin >> indices[i * 3 + 0] >> indices[i * 3 + 1] >> indices[i * 3 + 2];
  820.     }
  821.  
  822.     fin.close();
  823.  
  824.     //
  825.     // Pack the indices of all the meshes into one index buffer.
  826.     //
  827.  
  828.     const UINT vbByteSize = (UINT)vertices.size() * sizeof(Vertex);
  829.  
  830.     const UINT ibByteSize = (UINT)indices.size() * sizeof(std::int32_t);
  831.  
  832.     auto geo = std::make_unique<MeshGeometry>();
  833.     geo->Name = "skullGeo";
  834.  
  835.     ThrowIfFailed(D3DCreateBlob(vbByteSize, &geo->VertexBufferCPU));
  836.     CopyMemory(geo->VertexBufferCPU->GetBufferPointer(), vertices.data(), vbByteSize);
  837.  
  838.     ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
  839.     CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);
  840.  
  841.     geo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  842.         mCommandList.Get(), vertices.data(), vbByteSize, geo->VertexBufferUploader);
  843.  
  844.     geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  845.         mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);
  846.  
  847.     geo->VertexByteStride = sizeof(Vertex);
  848.     geo->VertexBufferByteSize = vbByteSize;
  849.     geo->IndexFormat = DXGI_FORMAT_R32_UINT;
  850.     geo->IndexBufferByteSize = ibByteSize;
  851.  
  852.     SubmeshGeometry submesh;
  853.     submesh.IndexCount = (UINT)indices.size();
  854.     submesh.StartIndexLocation = 0;
  855.     submesh.BaseVertexLocation = 0;
  856.     submesh.Bounds = bounds;
  857.  
  858.     geo->DrawArgs["skull"] = submesh;
  859.  
  860.     mGeometries[geo->Name] = std::move(geo);
  861. }
  862.  
  863. void DynamicCubeMapApp::BuildShapeGeometry()
  864. {
  865.     GeometryGenerator geoGen;
  866.     GeometryGenerator::MeshData box = geoGen.CreateBox(1.0f, 1.0f, 1.0f, 3);
  867.     GeometryGenerator::MeshData grid = geoGen.CreateGrid(20.0f, 30.0f, 60, 40);
  868.     GeometryGenerator::MeshData sphere = geoGen.CreateSphere(0.5f, 20, 20);
  869.     GeometryGenerator::MeshData cylinder = geoGen.CreateCylinder(0.5f, 0.3f, 3.0f, 20, 20);
  870.  
  871.     //
  872.     // We are concatenating all the geometry into one big vertex/index buffer.  So
  873.     // define the regions in the buffer each submesh covers.
  874.     //
  875.  
  876.     // Cache the vertex offsets to each object in the concatenated vertex buffer.
  877.     UINT boxVertexOffset = 0;
  878.     UINT gridVertexOffset = (UINT)box.Vertices.size();
  879.     UINT sphereVertexOffset = gridVertexOffset + (UINT)grid.Vertices.size();
  880.     UINT cylinderVertexOffset = sphereVertexOffset + (UINT)sphere.Vertices.size();
  881.  
  882.     // Cache the starting index for each object in the concatenated index buffer.
  883.     UINT boxIndexOffset = 0;
  884.     UINT gridIndexOffset = (UINT)box.Indices32.size();
  885.     UINT sphereIndexOffset = gridIndexOffset + (UINT)grid.Indices32.size();
  886.     UINT cylinderIndexOffset = sphereIndexOffset + (UINT)sphere.Indices32.size();
  887.  
  888.     SubmeshGeometry boxSubmesh;
  889.     boxSubmesh.IndexCount = (UINT)box.Indices32.size();
  890.     boxSubmesh.StartIndexLocation = boxIndexOffset;
  891.     boxSubmesh.BaseVertexLocation = boxVertexOffset;
  892.  
  893.     SubmeshGeometry gridSubmesh;
  894.     gridSubmesh.IndexCount = (UINT)grid.Indices32.size();
  895.     gridSubmesh.StartIndexLocation = gridIndexOffset;
  896.     gridSubmesh.BaseVertexLocation = gridVertexOffset;
  897.  
  898.     SubmeshGeometry sphereSubmesh;
  899.     sphereSubmesh.IndexCount = (UINT)sphere.Indices32.size();
  900.     sphereSubmesh.StartIndexLocation = sphereIndexOffset;
  901.     sphereSubmesh.BaseVertexLocation = sphereVertexOffset;
  902.  
  903.     SubmeshGeometry cylinderSubmesh;
  904.     cylinderSubmesh.IndexCount = (UINT)cylinder.Indices32.size();
  905.     cylinderSubmesh.StartIndexLocation = cylinderIndexOffset;
  906.     cylinderSubmesh.BaseVertexLocation = cylinderVertexOffset;
  907.  
  908.     //
  909.     // Extract the vertex elements we are interested in and pack the
  910.     // vertices of all the meshes into one vertex buffer.
  911.     //
  912.  
  913.     auto totalVertexCount =
  914.         box.Vertices.size() +
  915.         grid.Vertices.size() +
  916.         sphere.Vertices.size() +
  917.         cylinder.Vertices.size();
  918.  
  919.     std::vector<Vertex> vertices(totalVertexCount);
  920.  
  921.     UINT k = 0;
  922.     for(size_t i = 0; i < box.Vertices.size(); ++i, ++k)
  923.     {
  924.         vertices[k].Pos = box.Vertices[i].Position;
  925.         vertices[k].Normal = box.Vertices[i].Normal;
  926.         vertices[k].TexC = box.Vertices[i].TexC;
  927.     }
  928.  
  929.     for(size_t i = 0; i < grid.Vertices.size(); ++i, ++k)
  930.     {
  931.         vertices[k].Pos = grid.Vertices[i].Position;
  932.         vertices[k].Normal = grid.Vertices[i].Normal;
  933.         vertices[k].TexC = grid.Vertices[i].TexC;
  934.     }
  935.  
  936.     for(size_t i = 0; i < sphere.Vertices.size(); ++i, ++k)
  937.     {
  938.         vertices[k].Pos = sphere.Vertices[i].Position;
  939.         vertices[k].Normal = sphere.Vertices[i].Normal;
  940.         vertices[k].TexC = sphere.Vertices[i].TexC;
  941.     }
  942.  
  943.     for(size_t i = 0; i < cylinder.Vertices.size(); ++i, ++k)
  944.     {
  945.         vertices[k].Pos = cylinder.Vertices[i].Position;
  946.         vertices[k].Normal = cylinder.Vertices[i].Normal;
  947.         vertices[k].TexC = cylinder.Vertices[i].TexC;
  948.     }
  949.  
  950.     std::vector<std::uint16_t> indices;
  951.     indices.insert(indices.end(), std::begin(box.GetIndices16()), std::end(box.GetIndices16()));
  952.     indices.insert(indices.end(), std::begin(grid.GetIndices16()), std::end(grid.GetIndices16()));
  953.     indices.insert(indices.end(), std::begin(sphere.GetIndices16()), std::end(sphere.GetIndices16()));
  954.     indices.insert(indices.end(), std::begin(cylinder.GetIndices16()), std::end(cylinder.GetIndices16()));
  955.  
  956.     const UINT vbByteSize = (UINT)vertices.size() * sizeof(Vertex);
  957.     const UINT ibByteSize = (UINT)indices.size()  * sizeof(std::uint16_t);
  958.  
  959.     auto geo = std::make_unique<MeshGeometry>();
  960.     geo->Name = "shapeGeo";
  961.  
  962.     ThrowIfFailed(D3DCreateBlob(vbByteSize, &geo->VertexBufferCPU));
  963.     CopyMemory(geo->VertexBufferCPU->GetBufferPointer(), vertices.data(), vbByteSize);
  964.  
  965.     ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
  966.     CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);
  967.  
  968.     geo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  969.         mCommandList.Get(), vertices.data(), vbByteSize, geo->VertexBufferUploader);
  970.  
  971.     geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  972.         mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);
  973.  
  974.     geo->VertexByteStride = sizeof(Vertex);
  975.     geo->VertexBufferByteSize = vbByteSize;
  976.     geo->IndexFormat = DXGI_FORMAT_R16_UINT;
  977.     geo->IndexBufferByteSize = ibByteSize;
  978.  
  979.     geo->DrawArgs["box"] = boxSubmesh;
  980.     geo->DrawArgs["grid"] = gridSubmesh;
  981.     geo->DrawArgs["sphere"] = sphereSubmesh;
  982.     geo->DrawArgs["cylinder"] = cylinderSubmesh;
  983.  
  984.     mGeometries[geo->Name] = std::move(geo);
  985. }
  986.  
  987. void DynamicCubeMapApp::BuildPSOs()
  988. {
  989.     D3D12_GRAPHICS_PIPELINE_STATE_DESC opaquePsoDesc;
  990.  
  991.     //
  992.     // PSO for opaque objects.
  993.     //
  994.     ZeroMemory(&opaquePsoDesc, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));
  995.     opaquePsoDesc.InputLayout = { mInputLayout.data(), (UINT)mInputLayout.size() };
  996.     opaquePsoDesc.pRootSignature = mRootSignature.Get();
  997.     opaquePsoDesc.VS = 
  998.     { 
  999.         reinterpret_cast<BYTE*>(mShaders["standardVS"]->GetBufferPointer()), 
  1000.         mShaders["standardVS"]->GetBufferSize()
  1001.     };
  1002.     opaquePsoDesc.PS = 
  1003.     { 
  1004.         reinterpret_cast<BYTE*>(mShaders["opaquePS"]->GetBufferPointer()),
  1005.         mShaders["opaquePS"]->GetBufferSize()
  1006.     };
  1007.     opaquePsoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
  1008.     opaquePsoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
  1009.     opaquePsoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
  1010.     opaquePsoDesc.SampleMask = UINT_MAX;
  1011.     opaquePsoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
  1012.     opaquePsoDesc.NumRenderTargets = 1;
  1013.     opaquePsoDesc.RTVFormats[0] = mBackBufferFormat;
  1014.     opaquePsoDesc.SampleDesc.Count = m4xMsaaState ? 4 : 1;
  1015.     opaquePsoDesc.SampleDesc.Quality = m4xMsaaState ? (m4xMsaaQuality - 1) : 0;
  1016.     opaquePsoDesc.DSVFormat = mDepthStencilFormat;
  1017.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&opaquePsoDesc, IID_PPV_ARGS(&mPSOs["opaque"])));
  1018.  
  1019.     //
  1020.     // PSO for sky.
  1021.     //
  1022.     D3D12_GRAPHICS_PIPELINE_STATE_DESC skyPsoDesc = opaquePsoDesc;
  1023.  
  1024.     // The camera is inside the sky sphere, so just turn off culling.
  1025.     skyPsoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
  1026.  
  1027.     // Make sure the depth function is LESS_EQUAL and not just LESS.  
  1028.     // Otherwise, the normalized depth values at z = 1 (NDC) will 
  1029.     // fail the depth test if the depth buffer was cleared to 1.
  1030.     skyPsoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
  1031.     skyPsoDesc.pRootSignature = mRootSignature.Get();
  1032.     skyPsoDesc.VS =
  1033.     {
  1034.         reinterpret_cast<BYTE*>(mShaders["skyVS"]->GetBufferPointer()),
  1035.         mShaders["skyVS"]->GetBufferSize()
  1036.     };
  1037.     skyPsoDesc.PS =
  1038.     {
  1039.         reinterpret_cast<BYTE*>(mShaders["skyPS"]->GetBufferPointer()),
  1040.         mShaders["skyPS"]->GetBufferSize()
  1041.     };
  1042.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&skyPsoDesc, IID_PPV_ARGS(&mPSOs["sky"])));
  1043.  
  1044. }
  1045.  
  1046. void DynamicCubeMapApp::BuildFrameResources()
  1047. {
  1048.     for(int i = 0; i < gNumFrameResources; ++i)
  1049.     {
  1050.         mFrameResources.push_back(std::make_unique<FrameResource>(md3dDevice.Get(),
  1051.             7, (UINT)mAllRitems.size(), (UINT)mMaterials.size()));
  1052.     }
  1053. }
  1054.  
  1055. void DynamicCubeMapApp::BuildMaterials()
  1056. {
  1057.     auto bricks0 = std::make_unique<Material>();
  1058.     bricks0->Name = "bricks0";
  1059.     bricks0->MatCBIndex = 0;
  1060.     bricks0->DiffuseSrvHeapIndex = 0;
  1061.     bricks0->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
  1062.     bricks0->FresnelR0 = XMFLOAT3(0.1f, 0.1f, 0.1f);
  1063.     bricks0->Roughness = 0.3f;
  1064.  
  1065.     auto tile0 = std::make_unique<Material>();
  1066.     tile0->Name = "tile0";
  1067.     tile0->MatCBIndex = 1;
  1068.     tile0->DiffuseSrvHeapIndex = 1;
  1069.     tile0->DiffuseAlbedo = XMFLOAT4(0.9f, 0.9f, 0.9f, 1.0f);
  1070.     tile0->FresnelR0 = XMFLOAT3(0.2f, 0.2f, 0.2f);
  1071.     tile0->Roughness = 0.1f;
  1072.  
  1073.     auto mirror0 = std::make_unique<Material>();
  1074.     mirror0->Name = "mirror0";
  1075.     mirror0->MatCBIndex = 2;
  1076.     mirror0->DiffuseSrvHeapIndex = 2;
  1077.     mirror0->DiffuseAlbedo = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f);
  1078.     mirror0->FresnelR0 = XMFLOAT3(0.98f, 0.97f, 0.95f);
  1079.     mirror0->Roughness = 0.1f;
  1080.  
  1081.     auto sky = std::make_unique<Material>();
  1082.     sky->Name = "sky";
  1083.     sky->MatCBIndex = 3;
  1084.     sky->DiffuseSrvHeapIndex = 3;
  1085.     sky->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
  1086.     sky->FresnelR0 = XMFLOAT3(0.1f, 0.1f, 0.1f);
  1087.     sky->Roughness = 1.0f;
  1088.  
  1089.     auto skullMat = std::make_unique<Material>();
  1090.     skullMat->Name = "skullMat";
  1091.     skullMat->MatCBIndex = 4;
  1092.     skullMat->DiffuseSrvHeapIndex = 2;
  1093.     skullMat->DiffuseAlbedo = XMFLOAT4(0.8f, 0.8f, 0.8f, 1.0f);
  1094.     skullMat->FresnelR0 = XMFLOAT3(0.2f, 0.2f, 0.2f);
  1095.     skullMat->Roughness = 0.2f;
  1096.  
  1097.     mMaterials["bricks0"] = std::move(bricks0);
  1098.     mMaterials["tile0"] = std::move(tile0);
  1099.     mMaterials["mirror0"] = std::move(mirror0);
  1100.     mMaterials["sky"] = std::move(sky);
  1101.     mMaterials["skullMat"] = std::move(skullMat);
  1102. }
  1103.  
  1104. void DynamicCubeMapApp::BuildRenderItems()
  1105. {
  1106.     auto skyRitem = std::make_unique<RenderItem>();
  1107.     XMStoreFloat4x4(&skyRitem->World, XMMatrixScaling(5000.0f, 5000.0f, 5000.0f));
  1108.     skyRitem->TexTransform = MathHelper::Identity4x4();
  1109.     skyRitem->ObjCBIndex = 0;
  1110.     skyRitem->Mat = mMaterials["sky"].get();
  1111.     skyRitem->Geo = mGeometries["shapeGeo"].get();
  1112.     skyRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1113.     skyRitem->IndexCount = skyRitem->Geo->DrawArgs["sphere"].IndexCount;
  1114.     skyRitem->StartIndexLocation = skyRitem->Geo->DrawArgs["sphere"].StartIndexLocation;
  1115.     skyRitem->BaseVertexLocation = skyRitem->Geo->DrawArgs["sphere"].BaseVertexLocation;
  1116.  
  1117.     mRitemLayer[(int)RenderLayer::Sky].push_back(skyRitem.get());
  1118.     mAllRitems.push_back(std::move(skyRitem));
  1119.  
  1120.     auto skullRitem = std::make_unique<RenderItem>();
  1121.     skullRitem->World = MathHelper::Identity4x4();
  1122.     skullRitem->TexTransform = MathHelper::Identity4x4();
  1123.     skullRitem->ObjCBIndex = 1;
  1124.     skullRitem->Mat = mMaterials["skullMat"].get();
  1125.     skullRitem->Geo = mGeometries["skullGeo"].get();
  1126.     skullRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1127.     skullRitem->IndexCount = skullRitem->Geo->DrawArgs["skull"].IndexCount;
  1128.     skullRitem->StartIndexLocation = skullRitem->Geo->DrawArgs["skull"].StartIndexLocation;
  1129.     skullRitem->BaseVertexLocation = skullRitem->Geo->DrawArgs["skull"].BaseVertexLocation;
  1130.  
  1131.     mSkullRitem = skullRitem.get();
  1132.  
  1133.     mRitemLayer[(int)RenderLayer::Opaque].push_back(skullRitem.get());
  1134.     mAllRitems.push_back(std::move(skullRitem));
  1135.  
  1136.     auto boxRitem = std::make_unique<RenderItem>();
  1137.     XMStoreFloat4x4(&boxRitem->World, XMMatrixScaling(2.0f, 1.0f, 2.0f)*XMMatrixTranslation(0.0f, 0.5f, 0.0f));
  1138.     XMStoreFloat4x4(&boxRitem->TexTransform, XMMatrixScaling(1.0f, 1.0f, 1.0f));
  1139.     boxRitem->ObjCBIndex = 2;
  1140.     boxRitem->Mat = mMaterials["bricks0"].get();
  1141.     boxRitem->Geo = mGeometries["shapeGeo"].get();
  1142.     boxRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1143.     boxRitem->IndexCount = boxRitem->Geo->DrawArgs["box"].IndexCount;
  1144.     boxRitem->StartIndexLocation = boxRitem->Geo->DrawArgs["box"].StartIndexLocation;
  1145.     boxRitem->BaseVertexLocation = boxRitem->Geo->DrawArgs["box"].BaseVertexLocation;
  1146.  
  1147.     mRitemLayer[(int)RenderLayer::Opaque].push_back(boxRitem.get());
  1148.     mAllRitems.push_back(std::move(boxRitem));
  1149.  
  1150.     auto globeRitem = std::make_unique<RenderItem>();
  1151.     XMStoreFloat4x4(&globeRitem->World, XMMatrixScaling(2.0f, 2.0f, 2.0f)*XMMatrixTranslation(0.0f, 2.0f, 0.0f));
  1152.     XMStoreFloat4x4(&globeRitem->TexTransform, XMMatrixScaling(1.0f, 1.0f, 1.0f));
  1153.     globeRitem->ObjCBIndex = 3;
  1154.     globeRitem->Mat = mMaterials["mirror0"].get();
  1155.     globeRitem->Geo = mGeometries["shapeGeo"].get();
  1156.     globeRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1157.     globeRitem->IndexCount = globeRitem->Geo->DrawArgs["sphere"].IndexCount;
  1158.     globeRitem->StartIndexLocation = globeRitem->Geo->DrawArgs["sphere"].StartIndexLocation;
  1159.     globeRitem->BaseVertexLocation = globeRitem->Geo->DrawArgs["sphere"].BaseVertexLocation;
  1160.  
  1161.     mRitemLayer[(int)RenderLayer::OpaqueDynamicReflectors].push_back(globeRitem.get());
  1162.     mAllRitems.push_back(std::move(globeRitem));
  1163.  
  1164.     auto gridRitem = std::make_unique<RenderItem>();
  1165.     gridRitem->World = MathHelper::Identity4x4();
  1166.     XMStoreFloat4x4(&gridRitem->TexTransform, XMMatrixScaling(8.0f, 8.0f, 1.0f));
  1167.     gridRitem->ObjCBIndex = 4;
  1168.     gridRitem->Mat = mMaterials["tile0"].get();
  1169.     gridRitem->Geo = mGeometries["shapeGeo"].get();
  1170.     gridRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1171.     gridRitem->IndexCount = gridRitem->Geo->DrawArgs["grid"].IndexCount;
  1172.     gridRitem->StartIndexLocation = gridRitem->Geo->DrawArgs["grid"].StartIndexLocation;
  1173.     gridRitem->BaseVertexLocation = gridRitem->Geo->DrawArgs["grid"].BaseVertexLocation;
  1174.  
  1175.     mRitemLayer[(int)RenderLayer::Opaque].push_back(gridRitem.get());
  1176.     mAllRitems.push_back(std::move(gridRitem));
  1177.  
  1178.     XMMATRIX brickTexTransform = XMMatrixScaling(1.5f, 2.0f, 1.0f);
  1179.     UINT objCBIndex = 5;
  1180.     for(int i = 0; i < 5; ++i)
  1181.     {
  1182.         auto leftCylRitem = std::make_unique<RenderItem>();
  1183.         auto rightCylRitem = std::make_unique<RenderItem>();
  1184.         auto leftSphereRitem = std::make_unique<RenderItem>();
  1185.         auto rightSphereRitem = std::make_unique<RenderItem>();
  1186.  
  1187.         XMMATRIX leftCylWorld = XMMatrixTranslation(-5.0f, 1.5f, -10.0f + i*5.0f);
  1188.         XMMATRIX rightCylWorld = XMMatrixTranslation(+5.0f, 1.5f, -10.0f + i*5.0f);
  1189.  
  1190.         XMMATRIX leftSphereWorld = XMMatrixTranslation(-5.0f, 3.5f, -10.0f + i*5.0f);
  1191.         XMMATRIX rightSphereWorld = XMMatrixTranslation(+5.0f, 3.5f, -10.0f + i*5.0f);
  1192.  
  1193.         XMStoreFloat4x4(&leftCylRitem->World, rightCylWorld);
  1194.         XMStoreFloat4x4(&leftCylRitem->TexTransform, brickTexTransform);
  1195.         leftCylRitem->ObjCBIndex = objCBIndex++;
  1196.         leftCylRitem->Mat = mMaterials["bricks0"].get();
  1197.         leftCylRitem->Geo = mGeometries["shapeGeo"].get();
  1198.         leftCylRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1199.         leftCylRitem->IndexCount = leftCylRitem->Geo->DrawArgs["cylinder"].IndexCount;
  1200.         leftCylRitem->StartIndexLocation = leftCylRitem->Geo->DrawArgs["cylinder"].StartIndexLocation;
  1201.         leftCylRitem->BaseVertexLocation = leftCylRitem->Geo->DrawArgs["cylinder"].BaseVertexLocation;
  1202.  
  1203.         XMStoreFloat4x4(&rightCylRitem->World, leftCylWorld);
  1204.         XMStoreFloat4x4(&rightCylRitem->TexTransform, brickTexTransform);
  1205.         rightCylRitem->ObjCBIndex = objCBIndex++;
  1206.         rightCylRitem->Mat = mMaterials["bricks0"].get();
  1207.         rightCylRitem->Geo = mGeometries["shapeGeo"].get();
  1208.         rightCylRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1209.         rightCylRitem->IndexCount = rightCylRitem->Geo->DrawArgs["cylinder"].IndexCount;
  1210.         rightCylRitem->StartIndexLocation = rightCylRitem->Geo->DrawArgs["cylinder"].StartIndexLocation;
  1211.         rightCylRitem->BaseVertexLocation = rightCylRitem->Geo->DrawArgs["cylinder"].BaseVertexLocation;
  1212.  
  1213.         XMStoreFloat4x4(&leftSphereRitem->World, leftSphereWorld);
  1214.         leftSphereRitem->TexTransform = MathHelper::Identity4x4();
  1215.         leftSphereRitem->ObjCBIndex = objCBIndex++;
  1216.         leftSphereRitem->Mat = mMaterials["mirror0"].get();
  1217.         leftSphereRitem->Geo = mGeometries["shapeGeo"].get();
  1218.         leftSphereRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1219.         leftSphereRitem->IndexCount = leftSphereRitem->Geo->DrawArgs["sphere"].IndexCount;
  1220.         leftSphereRitem->StartIndexLocation = leftSphereRitem->Geo->DrawArgs["sphere"].StartIndexLocation;
  1221.         leftSphereRitem->BaseVertexLocation = leftSphereRitem->Geo->DrawArgs["sphere"].BaseVertexLocation;
  1222.  
  1223.         XMStoreFloat4x4(&rightSphereRitem->World, rightSphereWorld);
  1224.         rightSphereRitem->TexTransform = MathHelper::Identity4x4();
  1225.         rightSphereRitem->ObjCBIndex = objCBIndex++;
  1226.         rightSphereRitem->Mat = mMaterials["mirror0"].get();
  1227.         rightSphereRitem->Geo = mGeometries["shapeGeo"].get();
  1228.         rightSphereRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1229.         rightSphereRitem->IndexCount = rightSphereRitem->Geo->DrawArgs["sphere"].IndexCount;
  1230.         rightSphereRitem->StartIndexLocation = rightSphereRitem->Geo->DrawArgs["sphere"].StartIndexLocation;
  1231.         rightSphereRitem->BaseVertexLocation = rightSphereRitem->Geo->DrawArgs["sphere"].BaseVertexLocation;
  1232.  
  1233.         mRitemLayer[(int)RenderLayer::Opaque].push_back(leftCylRitem.get());
  1234.         mRitemLayer[(int)RenderLayer::Opaque].push_back(rightCylRitem.get());
  1235.         mRitemLayer[(int)RenderLayer::Opaque].push_back(leftSphereRitem.get());
  1236.         mRitemLayer[(int)RenderLayer::Opaque].push_back(rightSphereRitem.get());
  1237.  
  1238.         mAllRitems.push_back(std::move(leftCylRitem));
  1239.         mAllRitems.push_back(std::move(rightCylRitem));
  1240.         mAllRitems.push_back(std::move(leftSphereRitem));
  1241.         mAllRitems.push_back(std::move(rightSphereRitem));
  1242.     }
  1243. }
  1244.  
  1245. void DynamicCubeMapApp::DrawRenderItems(ID3D12GraphicsCommandList* cmdList, const std::vector<RenderItem*>& ritems)
  1246. {
  1247.     UINT objCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(ObjectConstants));
  1248.  
  1249.     auto objectCB = mCurrFrameResource->ObjectCB->Resource();
  1250.  
  1251.     // For each render item...
  1252.     for(size_t i = 0; i < ritems.size(); ++i)
  1253.     {
  1254.         auto ri = ritems[i];
  1255.  
  1256.         cmdList->IASetVertexBuffers(0, 1, &ri->Geo->VertexBufferView());
  1257.         cmdList->IASetIndexBuffer(&ri->Geo->IndexBufferView());
  1258.         cmdList->IASetPrimitiveTopology(ri->PrimitiveType);
  1259.  
  1260.         D3D12_GPU_VIRTUAL_ADDRESS objCBAddress = objectCB->GetGPUVirtualAddress() + ri->ObjCBIndex*objCBByteSize;
  1261.  
  1262.         cmdList->SetGraphicsRootConstantBufferView(0, objCBAddress);
  1263.  
  1264.         cmdList->DrawIndexedInstanced(ri->IndexCount, 1, ri->StartIndexLocation, ri->BaseVertexLocation, 0);
  1265.     }
  1266. }
  1267.  
  1268. void DynamicCubeMapApp::DrawSceneToCubeMap()
  1269. {
  1270.     mCommandList->RSSetViewports(1, &mDynamicCubeMap->Viewport());
  1271.     mCommandList->RSSetScissorRects(1, &mDynamicCubeMap->ScissorRect());
  1272.  
  1273.     // Change to RENDER_TARGET.
  1274.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mDynamicCubeMap->Resource(),
  1275.         D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET));
  1276.  
  1277.     UINT passCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(PassConstants));
  1278.  
  1279.     // For each cube map face.
  1280.     for(int i = 0; i < 6; ++i)
  1281.     {
  1282.         // Clear the back buffer and depth buffer.
  1283.         mCommandList->ClearRenderTargetView(mDynamicCubeMap->Rtv(i), Colors::LightSteelBlue, 0, nullptr);
  1284.         mCommandList->ClearDepthStencilView(mCubeDSV, D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr);
  1285.  
  1286.         // Specify the buffers we are going to render to.
  1287.         mCommandList->OMSetRenderTargets(1, &mDynamicCubeMap->Rtv(i), true, &mCubeDSV);
  1288.  
  1289.         // Bind the pass constant buffer for this cube map face so we use 
  1290.         // the right view/proj matrix for this cube face.
  1291.         auto passCB = mCurrFrameResource->PassCB->Resource();
  1292.         D3D12_GPU_VIRTUAL_ADDRESS passCBAddress = passCB->GetGPUVirtualAddress() + (1+i)*passCBByteSize;
  1293.         mCommandList->SetGraphicsRootConstantBufferView(1, passCBAddress);
  1294.  
  1295.         DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Opaque]);
  1296.  
  1297.         mCommandList->SetPipelineState(mPSOs["sky"].Get());
  1298.         DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Sky]);
  1299.  
  1300.         mCommandList->SetPipelineState(mPSOs["opaque"].Get());
  1301.     }
  1302.  
  1303.     // Change back to GENERIC_READ so we can read the texture in a shader.
  1304.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mDynamicCubeMap->Resource(),
  1305.         D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ));
  1306. }
  1307.  
  1308. std::array<const CD3DX12_STATIC_SAMPLER_DESC, 6> DynamicCubeMapApp::GetStaticSamplers()
  1309. {
  1310.     // Applications usually only need a handful of samplers.  So just define them all up front
  1311.     // and keep them available as part of the root signature.  
  1312.  
  1313.     const CD3DX12_STATIC_SAMPLER_DESC pointWrap(
  1314.         0, // shaderRegister
  1315.         D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
  1316.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  1317.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  1318.         D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
  1319.  
  1320.     const CD3DX12_STATIC_SAMPLER_DESC pointClamp(
  1321.         1, // shaderRegister
  1322.         D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
  1323.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  1324.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  1325.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
  1326.  
  1327.     const CD3DX12_STATIC_SAMPLER_DESC linearWrap(
  1328.         2, // shaderRegister
  1329.         D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
  1330.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  1331.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  1332.         D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
  1333.  
  1334.     const CD3DX12_STATIC_SAMPLER_DESC linearClamp(
  1335.         3, // shaderRegister
  1336.         D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
  1337.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  1338.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  1339.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
  1340.  
  1341.     const CD3DX12_STATIC_SAMPLER_DESC anisotropicWrap(
  1342.         4, // shaderRegister
  1343.         D3D12_FILTER_ANISOTROPIC, // filter
  1344.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  1345.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  1346.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressW
  1347.         0.0f,                             // mipLODBias
  1348.         8);                               // maxAnisotropy
  1349.  
  1350.     const CD3DX12_STATIC_SAMPLER_DESC anisotropicClamp(
  1351.         5, // shaderRegister
  1352.         D3D12_FILTER_ANISOTROPIC, // filter
  1353.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  1354.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  1355.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressW
  1356.         0.0f,                              // mipLODBias
  1357.         8);                                // maxAnisotropy
  1358.  
  1359.     return { 
  1360.         pointWrap, pointClamp,
  1361.         linearWrap, linearClamp, 
  1362.         anisotropicWrap, anisotropicClamp };
  1363. }
  1364.  
  1365. void DynamicCubeMapApp::BuildCubeFaceCamera(float x, float y, float z)
  1366. {
  1367.     // Generate the cube map about the given position.
  1368.     XMFLOAT3 center(x, y, z);
  1369.     XMFLOAT3 worldUp(0.0f, 1.0f, 0.0f);
  1370.  
  1371.     // Look along each coordinate axis.
  1372.     XMFLOAT3 targets[6] =
  1373.     {
  1374.         XMFLOAT3(x + 1.0f, y, z), // +X
  1375.         XMFLOAT3(x - 1.0f, y, z), // -X
  1376.         XMFLOAT3(x, y + 1.0f, z), // +Y
  1377.         XMFLOAT3(x, y - 1.0f, z), // -Y
  1378.         XMFLOAT3(x, y, z + 1.0f), // +Z
  1379.         XMFLOAT3(x, y, z - 1.0f)  // -Z
  1380.     };
  1381.  
  1382.     // Use world up vector (0,1,0) for all directions except +Y/-Y.  In these cases, we
  1383.     // are looking down +Y or -Y, so we need a different "up" vector.
  1384.     XMFLOAT3 ups[6] =
  1385.     {
  1386.         XMFLOAT3(0.0f, 1.0f, 0.0f),  // +X
  1387.         XMFLOAT3(0.0f, 1.0f, 0.0f),  // -X
  1388.         XMFLOAT3(0.0f, 0.0f, -1.0f), // +Y
  1389.         XMFLOAT3(0.0f, 0.0f, +1.0f), // -Y
  1390.         XMFLOAT3(0.0f, 1.0f, 0.0f),     // +Z
  1391.         XMFLOAT3(0.0f, 1.0f, 0.0f)     // -Z
  1392.     };
  1393.  
  1394.     for(int i = 0; i < 6; ++i)
  1395.     {
  1396.         mCubeMapCamera[i].LookAt(center, targets[i], ups[i]);
  1397.         mCubeMapCamera[i].SetLens(0.5f*XM_PI, 1.0f, 0.1f, 1000.0f);
  1398.         mCubeMapCamera[i].UpdateViewMatrix();
  1399.     }
  1400. }